package com.ocean.core.common.zookeeper;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;

import com.ocean.core.common.system.Constants;
import com.ocean.core.common.system.MyLogManager;
import com.ocean.core.common.system.SystemContext;

/** * @author Alex & E-mail:569246607@qq.com
      @date   2017年8月14日 
      @version 1.0 
 */
public class ServerDistrController implements ServerDistribute<String>{
	private  final Logger logger = MyLogManager.getLbsLogger();
	private  final ZooKeeperHolder holder;
	public ServerDistrController() throws Exception{
		holder=new ZooKeeperHolder();
        init();
	}
	private void init() throws Exception{
		//后期吧这个改成xml配置
		String hosts=SystemContext.getStaticPropertyHandler().get(Constants.ZOOKEEPER_ADDRESS);
		if(StringUtils.isEmpty(hosts)){
			logger.error("zookeeper config error,hosts address is empty");
			throw new  Exception("zookeeper config error,hosts address is empty");
		}
		int timeOut=SystemContext.getStaticPropertyHandler().getInt(Constants.ZOOKEEPER_TIMEOUT,1000);
		
	
		try {
			holder.connect(hosts, timeOut);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.error("connect to zookeeper error : IOException",e);
			throw new  Exception("connect to zookeeper error : IOException");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			logger.error("connect to zookeeper error : InterruptedException",e);
			throw new  Exception("connect to zookeeper error : InterruptedException");
		}
	}
	public List<String> getServers() throws Exception {
		// TODO Auto-generated method stub
		String path=SystemContext.getStaticPropertyHandler().get(Constants.ZOOKEEPER_LBS_PATH);
		if(StringUtils.isEmpty(path)){
			logger.error("zookeeper config error,lbs server path of zookeeper  is empty");
			throw new  Exception("zookeeper config error,lbs server path of zookeeper  is empty");
		}
		 List<String> servers=new ArrayList<String>();
		try {
			List<String> nodes=this.holder.getNodes(path);
			for(String node:nodes){
				byte[] data=holder.getData(path+File.separator+node);
				if(data!=null){
					String nodeData=new String(data);
					logger.debug("the lbs server node data:{}",nodeData);
					servers.add(nodeData);
				}
				
			}
            return servers;
		} catch (KeeperException e) {
			// TODO Auto-generated catch block
			logger.error("get lbs server node from zookeeper  error : KeeperException",e);
			throw new  Exception("get lbs server node from zookeeper  error : KeeperException");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			logger.error("get lbs server node from zookeeper  error :  InterruptedException",e);
			throw new  Exception("get lbs server node from zookeeper  error :  InterruptedException");
		}
	}

    protected class AbstractZooKeeper implements Watcher{
        protected ZooKeeper zooKeeper;
        protected CountDownLatch countDownLatch = new CountDownLatch(1); 

		public void connect(String hosts,int timeOut)throws IOException, InterruptedException{
	
				zooKeeper=new ZooKeeper(hosts,timeOut,this);
				countDownLatch.await();

		}
		public void process(WatchedEvent event) {
			// TODO Auto-generated method stub
	        if(event.getState() == KeeperState.SyncConnected){  
	            countDownLatch.countDown();  
	        }
		} 
    }
    protected class ZooKeeperHolder extends AbstractZooKeeper{
    	public List<String> getNodes(String path) throws KeeperException, InterruptedException{

            List<String> children = this.zooKeeper.getChildren(path, false);  
            if (children.isEmpty()) {  
            	logger.error("the node of path {} is empty!",path);
                return null;  
            }else{  
            	logger.info("the nodes of path {} : {}",path,children);
               return children; 
            }  

    	}
        public byte[] getData(String path) throws KeeperException, InterruptedException {  
            return  this.zooKeeper.getData(path, false,null);  
        }  
    }

}
